Skip to content

Adding package management infrastructure - #21564

Merged
coqbot-app[bot] merged 16 commits into
rocq-prover:masterfrom
rlepigre-skylabs-ai:package
Jul 8, 2026
Merged

Adding package management infrastructure#21564
coqbot-app[bot] merged 16 commits into
rocq-prover:masterfrom
rlepigre-skylabs-ai:package

Conversation

@rlepigre-skylabs-ai

@rlepigre-skylabs-ai rlepigre-skylabs-ai commented Jan 29, 2026

Copy link
Copy Markdown
Contributor

This PR implement rocq-prover/rfcs#101, whose goal is to add a proper notion of Rocq package (piggy-backing on findlib), setting a path towards the eventual removal of the infamous coq/user-contrib directory. This was discussed in a Rocq Call.

Summary of the changes

  • Rocq CLI tools (rocq c, rocq dep, ...) now accept a -package <pkg> argument (similar to that of ocamlfind).
  • A rocq find command was added to list installed packages (directory and Rocq module path), and allowing to obtain the necessary -Q / -I flags for a given list of packages (or all of them).
  • The Corelib and Ltac2 libraries are installed twice: once under coq/user-contrib for backwards compatibility, and once as Rocq packages.
  • The rocq makefile command now takes a --rocq-package <pkgname> argument which can be used to request the use of the new package infrastructure (not using it is deprecated), together with dependencies specified via -package. A --legacy-support flag can be used to also install under coq/user-contrib.

Testing done

Correct Rocq install

Checked that Rocq installs correctly with the new installation scheme, including Rocq packages rocq-core and rocq-core.ltac2 that can be requested as packages.

Correct rocq-stdlib install

Checked that the Rocq standard library can be ported to the new system (via rocq makefile), and installs correctly after applying the following changes.

diff --git a/.gitignore b/.gitignore
index a93e1261a9..e0410c6a3d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -164,3 +164,4 @@ user-contrib/Ltac2/dune
 .wrappers
 doc/stdlib/Library.fdb_latexmk
 doc/stdlib/Library.fls
+theories/META.*
diff --git a/theories/_CoqProject b/theories/_CoqProject
index b34d8dd88a..cc961853c7 100644
--- a/theories/_CoqProject
+++ b/theories/_CoqProject
@@ -1,3 +1,7 @@
+--rocq-package rocq-stdlib
+-package rocq-core
+--legacy-support
+--description "Rocq standard library"
 -R . Stdlib
 # When editing below lines, keep the theories/dune file in sync
 # to handle when requiring Rocq >= 9.2

Correct bignums install

Checked that a simple plugin (bignums) builds and install correctly using rocq makefile after the following changes.

diff --git a/Makefile b/Makefile
index 1da733b..c3b27b6 100644
--- a/Makefile
+++ b/Makefile
@@ -8,7 +8,8 @@ clean: Makefile.coq
 _CoqProject:;

 Makefile.coq: _CoqProject
-       $(COQBIN)rocq makefile -f _CoqProject -o Makefile.coq
+       $(COQBIN)rocq makefile -f _CoqProject -o Makefile.coq \
+               --rocq-package coq-bignums --legacy-support -package rocq-stdlib

 %: Makefile.coq
        $(MAKE) -f Makefile.coq $@

Ensured that this can work with dune

Opened a dune PR that enables using the new installation scheme from dune projects. This dune version was tested using ports of equations, rocq-stdpp, and rocq-iris. And also a composed build of the latter two.

@coqbot-app coqbot-app Bot added the needs: full CI The latest GitLab pipeline that ran was a light CI. Say "@coqbot run full ci" to get a full CI. label Jan 29, 2026
@rlepigre-skylabs-ai

rlepigre-skylabs-ai commented Jan 29, 2026

Copy link
Copy Markdown
Contributor Author

Regarding the adaptation of rocq makefile, I believe that we wouldn't even need the -package options to the various commands, and that rocqfind would be sufficient for compilation (provided that install packages follow the expected installation scheme). All we'd need to do is ask the user to give a list of package dependencies in a variable ROCQ_PACKAGES, and then we could do something like the following in the generated Makefile:

DEPS_ARGS := $(shell rocqfind -Q -I ${ROCQ_PACKAGES} | tr '\n' ' ')

We would then add ${DEPS_ARGS} to all invoked rocq commands, in addition to the -Q / -R / -I that are needed for the local plugins / theories, and things would just work.

Of course, we'd still need to make sure that make install respects the installation scheme.

@SkySkimmer

Copy link
Copy Markdown
Contributor
  • the -I argument and output of rocqfind seems wrong: -I dir as an argument of rocqdep / rocqc means "add dir to OCAMLPATH". Since rocqfind gets its info from OCAMLPATH it has nothing new to add. The output it gives is also wrong since it prints directories which don't lead to META files. Finally when the _CoqProject contains -I dir (because there is a local META in dir) it seems like rocqfind should be informed about it.

  • I don't understand the point of rocqfind, shouldn't rocqc/rocqdep understand -package directly? also what is the point of the cmxs output

@rlepigre-skylabs-ai

rlepigre-skylabs-ai commented Jan 30, 2026

Copy link
Copy Markdown
Contributor Author
  • the -I argument and output of rocqfind seems wrong: -I dir as an argument of rocqdep / rocqc means "add dir to OCAMLPATH". Since rocqfind gets its info from OCAMLPATH it has nothing new to add. The output it gives is also wrong since it prints directories which don't lead to META files.

Good point, I now only add -I for the directories containing the META file.

Finally when the _CoqProject contains -I dir (because there is a local META in dir) it seems like rocqfind should be informed about it.

Yeah, maybe. I was thinking of rocqfind as a way of looking up actually installed stuff, not something we'd use for local plugins for example. I also don't know if rocqfind is useful in itself, but I thought it could be useful for rocq makefile-generated Makefiles.

  • I don't understand the point of rocqfind, shouldn't rocqc/rocqdep understand -package directly? also what is the point of the cmxs output

Yeah, I think they probably should, yes.

I initially thought of the cmxs output as a way to get external dependencies, for example in Makefile rules, to get sounder builds when they change. However that's probably not necessary, because the .vo has the hash of the .cmxs it directly uses, right?

@rlepigre-skylabs-ai

Copy link
Copy Markdown
Contributor Author

Regarding adding a -package option to rocq c, what do you think is the best way to do that? I see there are several places in the code base where argument parsing is done, and I was hoping not to duplicate the code everywhere (rocq doc, rocqchk, ...).

@SkySkimmer

Copy link
Copy Markdown
Contributor

the .vo has the has of the .cmxs it directly uses, right?

if "has the has" is meant to be "contains the hash" then yes

@rlepigre-skylabs-ai

Copy link
Copy Markdown
Contributor Author

if "has the has" is meant to be "contains the hash" then yes

Oups, I edited the comment.

@rlepigre-skylabs-ai

Copy link
Copy Markdown
Contributor Author

I've now added the -package option in all places where I could find a -Q option being supported.

@rlepigre-skylabs-ai

Copy link
Copy Markdown
Contributor Author

@SkySkimmer what do you think should be the next steps here? Should I make it so that Corelib and Ltac2 get installed as packages (in addition to the current installation scheme)?

It's also not clear to me how to make tests for this PR. Any recommendation on that front?

@SkySkimmer

Copy link
Copy Markdown
Contributor

I still don't understand what the transition is supposed to look like.
Are we supposed to install copies of packages in user-contrib and in their own lib/ subdir? That sounds like a waste of disk space.

@rlepigre-skylabs-ai

Copy link
Copy Markdown
Contributor Author

That seems like the easiest thing to do (potentially using symbolic links instead of actual copies, but that might lead to problems). Do you see another alternative?

@SkySkimmer

Copy link
Copy Markdown
Contributor

I don't think the argument parsing in coqproject_file and coqargs are the right places to call resolve. Is findlib even initialized when we're in that code?

It's also not clear to me how to make tests for this PR. Any recommendation on that front?

test-suite/coq-makefile and test-suite/misc have tests which are arbitrary scripts

That seems like the easiest thing to do (potentially using symbolic links instead of actual copies, but that might lead to problems). Do you see another alternative?

If we have copies (including symbolic links) won't they get detected as conflicts? eg Require Prelude would say "found prelude.vo in lib/coq/theories/... and lib/rocq-core/..."

@rlepigre-skylabs-ai

Copy link
Copy Markdown
Contributor Author

That seems like the easiest thing to do (potentially using symbolic links instead of actual copies, but that might lead to problems). Do you see another alternative?

If we have copies (including symbolic links) won't they get detected as conflicts? eg Require Prelude would say "found prelude.vo in lib/coq/theories/... and lib/rocq-core/..."

I guess that any particular project you should not rely both on packages and on lib/coq/user-contrib and lib/coq/theories. Either the package is ported, and only uses packages (and transitively for its deps), or it uses a legacy mode that does not allow packages.

Do you think something like that could work?

@SkySkimmer

Copy link
Copy Markdown
Contributor

Do we really want to force the transition order like that?

@rlepigre-skylabs-ai

Copy link
Copy Markdown
Contributor Author

I think this would be OK if package that have transitioned can be depended on by packages that have not, which would simply mean double-installing everything.

To me, it seems fine to require that a package can only transition if all its dependencies have.

@SkySkimmer

Copy link
Copy Markdown
Contributor

also isn't part of the point of this system that we can multiple packages using the same logical paths? but such packages can't be double installed

@rlepigre-skylabs-ai

Copy link
Copy Markdown
Contributor Author

Yeah, that's a good point. I guess they can't right now, so at least that's not a regression. We can only get that benefit when the legacy installation method is removed I guess.

@SkySkimmer

Copy link
Copy Markdown
Contributor

If we installed only once, we could have coqdep/coqc implicitly add -Q for all findlib packages if no -package is used.
Then a project must give either all or none of its dependencies with -package.
Installed conflicting packages would only error (ambiguous require) if attempted to be used without -package.

This may break dune though.

@rlepigre-skylabs-ai
rlepigre-skylabs-ai marked this pull request as ready for review April 9, 2026 16:26
@rlepigre-skylabs-ai
rlepigre-skylabs-ai requested review from a team as code owners April 9, 2026 16:26
@SkySkimmer

Copy link
Copy Markdown
Contributor

@coqbot run full ci

@coqbot-app coqbot-app Bot removed the needs: full CI The latest GitLab pipeline that ran was a light CI. Say "@coqbot run full ci" to get a full CI. label Jul 8, 2026

@SkySkimmer SkySkimmer left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should be ready AFAICT assuming CI doesn't suddenly break

@coqbot-app coqbot-app Bot added the needs: full CI The latest GitLab pipeline that ran was a light CI. Say "@coqbot run full ci" to get a full CI. label Jul 8, 2026
@rlepigre-skylabs-ai

Copy link
Copy Markdown
Contributor Author

@coqbot run full ci

@coqbot-app coqbot-app Bot removed the needs: full CI The latest GitLab pipeline that ran was a light CI. Say "@coqbot run full ci" to get a full CI. label Jul 8, 2026
@rlepigre-skylabs-ai

Copy link
Copy Markdown
Contributor Author

should be ready AFAICT assuming CI doesn't suddenly break

Sorry, I had not seen this message when I last pushed. I have extended the docs with explanations of the new installation layout.

They can be combined::

$ rocq find -Q -I my-package
-Q '/path/to/lib/my-package/rocq.d' MyPackage

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what's the quoting here? (ocaml, shell, other?)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's using Filename.quote, whose documentation starts with the following.

Return a quoted version of a file name, suitable for use as one argument in a command line, escaping all meta-characters.

@SkySkimmer SkySkimmer added this to the 9.3+rc1 milestone Jul 8, 2026
@SkySkimmer

Copy link
Copy Markdown
Contributor

@coqbot merge now

@coqbot-app
coqbot-app Bot merged commit d77b754 into rocq-prover:master Jul 8, 2026
8 of 9 checks passed
Comment thread tools/CoqMakefile.in
proux01 added a commit to proux01/rocq that referenced this pull request Jul 9, 2026
Fixing an unfortunate variable overlap from
rocq-prover#21564
proux01 added a commit to proux01/rocq that referenced this pull request Jul 9, 2026
Fixing an unfortunate variable overlap from
rocq-prover#21564
gares pushed a commit that referenced this pull request Jul 22, 2026
Fixing an unfortunate variable overlap from
#21564

(cherry picked from commit e964f5c)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

kind: feature New user-facing feature request or implementation.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants